/*
 * @Description:axios接口请求  详细配置看文档 https://www.kancloud.cn/yunye/axios/234845
 * @Author: dh
 * @Date: 2021-12-13 20:39:43
 * @LastEditors: dh
 * @LastEditTime: 2023-02-14 11:14:00
 */

import axios from "axios";
import config from "@/config/index"; // 路径配置
import { getToken } from "@/utils/auth";
import "@/api/mock.js";
import { showFullScreenLoading, tryHideFullScreenLoading } from "./loading";

const CancelToken = axios.CancelToken;

const whiteList = ["/users"]; // 不需要loading的接口

export const cancel = []; // 暴露给router文件,每次跳转就取消之前的请求

// 创建axios 实例
const service = axios.create({
	baseURL: config.baseURL, // BaseUrl
	timeout: 30000, // 请求超时时间 (包括查询和接收数据的时间)
	validateStatus: function (status) {
		return status >= 200 && status < 300; // 默认的  true 进入 resolve ，false 进入catch
	},
	headers: {},
});

// request 拦截器
service.interceptors.request.use(
	config => {
		// config.url = config.url + (config.url.indexOf('?') > 0 ? '&' : '?') + `cb=${new Date().getTime()}`;

		// 在发送请求之前做些什么
		if (getToken()) {
			config.headers["Authorization"] = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
		}
		// 存储 取消请求cancelToken 可以根据请求参数，判断切换路由是否取消该请求,
		config.cancelToken = new CancelToken(function executor(c) {
			// console.log(c.routeChangeCancel = config.params?config.params.routeChangeCancel:true);
			cancel.push(c);
		});

		const res = whiteList.some(v => config.url.includes(v));

		!res && showFullScreenLoading(); // 不在白名单就显示loading
		return config;
	},
	error => {
		// 对请求错误做些什么
		tryHideFullScreenLoading();
		return Promise.reject(error); // 直接return error 会进入then ，这样写会进入catch
	}
);

// response 拦截器 失败和成功的回调都可以获取到请求信息，token过去，可以获取刷新token使用
service.interceptors.response.use(
	response => {
		// 对响应数据做点什么
		tryHideFullScreenLoading();
		if (response.status === 200) {
			// 这里处理一些response 正常放回时的逻辑
			return Promise.resolve(response.data);
		} else {
			return Promise.reject(response);
		}
	},
	error => {
		// 判断是否主动取消的请求
		// console.log(axios.isCancel(error));

		// 对响应错误做点什么
		tryHideFullScreenLoading();
		if (!error.response) {
			// 断网处理
			if (!window.navigator.onLine) {
				// 断开网络了，可以让其跳转到断网页面
				return;
			}
			return Promise.reject(error);
		}
		if (error.response.status == 401) {
			// token 失效
			localStorage.removeItem("token");
			location.reload();
		}
		return Promise.reject(error); // 直接return， error 会进入then ，这样写会进入catch
		// return [null, error]; // 这样写可以在接口处用 await 接收错误了
	}
);

// 根据不同的状态码，生成不同的提示信息
const showStatus = status => {
	let message = "";
	// 这一坨代码可以使用策略模式进行优化
	switch (status) {
		case 400:
			message = "请求错误(400)";
			break;
		case 401:
			message = "未授权，请重新登录(401)";
			break;
		case 403:
			message = "拒绝访问(403)";
			break;
		case 404:
			message = "请求出错(404)";
			break;
		case 408:
			message = "请求超时(408)";
			break;
		case 500:
			message = "服务器错误(500)";
			break;
		case 501:
			message = "服务未实现(501)";
			break;
		case 502:
			message = "网络错误(502)";
			break;
		case 503:
			message = "服务不可用(503)";
			break;
		case 504:
			message = "网络超时(504)";
			break;
		case 505:
			message = "HTTP版本不受支持(505)";
			break;
		default:
			message = `连接出错(${status})!`;
	}
	return `${message}，请检查网络或联系管理员！`;
};

export default service;
